﻿using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading.Tasks;
using legend;

namespace ryscanner
{
    public class ScannerController
    {
        private Process process;
        private HandleRef handleRef;
        private MemoryScanner scanner;


        public byte[] getBytes(long address,int length) {
            return MemoryUtil64.ReadBytes(this.handleRef,address, (long)length);
        }

        public ScannerController(Process process) {
            this.process = process;
            this.handleRef = new HandleRef(process, process.Handle);
            this.scanner = new MemoryScanner(this.process, this.handleRef);
        }

        public List<long> scanBytes(byte[] value) {
            BoyerMoore boyerMoore = new BoyerMoore(value);
            List<BoyerMoore> l = new List<BoyerMoore>();
            l.Add(boyerMoore);
            this.scanner.SetBoyerMoores(l);
            return this.scanner.scan();
            
        }



        public bool isBaseAddr(long ptr) {
            return ptr >= this.process.MainModule.BaseAddress.ToInt64() && ptr < this.process.MainModule.ModuleMemorySize;
        }

        public byte[] memory(long ptr, int length , int offset) {
            long targetPtr = ptr + offset;
            return MemoryUtil64.ReadBytes(this.handleRef, targetPtr, (long)length);
        }

        public List<long> scanBetween(UInt32 min, UInt32 max) {
            return this.scanner.scanBetween(min, max);
        }


        public List<BaseAddress> baseAddressGuess(long address,int level,int offset) {
            return null;
        }
        public List<BaseAddress> baseAddressGuess(List<long> baseAddr,long address, int level, int offset)
        {
            if (level > 0) {
                List<long> ptrs = this.scanBetween((uint)(address - offset), (uint)address);
                List<BaseAddress> result = new List<BaseAddress>();
                foreach(var ptr in ptrs) {
                    if (this.isBaseAddr(ptr))
                    {
                        BaseAddress baseAddress = new BaseAddress();
                        baseAddress.baseAddr = true;
                        baseAddress.basePtr = address;
                        baseAddress.ptr = ptr;
                        baseAddress.offset = address - ptr;
                        result.Add(baseAddress);
                    }
                    else {
                        List<BaseAddress> baseAddresses =  this.baseAddressGuess(baseAddr, ptr, level--, offset);
                        if (baseAddresses != null && baseAddresses.Count > 0) {
                            result.AddRange(baseAddresses);
                        }
                    }
                }
                return result;
            }
            
            return null;
        }
    }
}
